package top.chenyaohua.utils;

import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import top.chenyaohua.bean.MethodInfo;
import top.chenyaohua.visit.PnuClassVisitor;
import top.chenyaohua.visit.PnuMethodVisitor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;

public class ClassUtils {


    public static  List<String> getParamsNames(String packageMethodName){

        List<String> paramNames = new ArrayList<>();
        try {
            //包名加类名加方法名
            String[] clasMethod = packageMethodName.split("[\\(|\\)|,]");
            int methodIndex = clasMethod[0].lastIndexOf(".");

            String methodName = clasMethod[0].substring(methodIndex+1);
            String className = clasMethod[0].substring(0,methodIndex);

            MethodInfo methodInfo = new MethodInfo(className,methodName);

            if(clasMethod.length > 1){
                String []types = new String[clasMethod.length-1];
                System.arraycopy(clasMethod,1,types,0,types.length);
                methodInfo.setTypes(Arrays.asList(types));
            }

            ClassReader cr = new ClassReader(className);
            ClassWriter cw = new ClassWriter(cr,ClassWriter.COMPUTE_FRAMES);
            PnuClassVisitor pcv = new PnuClassVisitor(cw,methodInfo);

            cr.accept(pcv,ClassReader.EXPAND_FRAMES);
            //方法对象
            PnuMethodVisitor pnuMethodVisitor = pcv.getMaps().get(packageMethodName);

            if (pnuMethodVisitor == null) {
                return paramNames;
            }

            //参数个数
            int size = methodInfo.getTypes().size();
            //局部变量表中的变量名和序号
            LinkedHashMap<Integer, String> params = pnuMethodVisitor.getParams();

            for (int i = 0; i < size; i++) {
                //如果不是静态方法 局部变量表0号索引位保存的是this对象
                //如果是静态方法局部变量表0号索引位保存的是第一个参数
                int index = methodInfo.enableStatic() ? i : (i + 1);

                paramNames.add( params.get( index ) );
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return paramNames;
    }

}
